package com.tilemap;

import java.util.ArrayList;
import java.util.HashMap;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;
import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;
import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;
import com.badlogic.gdx.graphics.g2d.tiled.TiledMap;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObject;
import com.badlogic.gdx.graphics.g2d.tiled.TiledObjectGroup;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.EdgeShape;
import com.badlogic.gdx.physics.box2d.World;

public class TiledMapHelper {
	private static final int[] layersList = { 0 };
	private World m_box2dworld;
	private float m_pixelpermeter;
	BodyDef m_groundbodydef;
	Body m_groundbody;

	public TiledMapHelper(World world,float pixelpermeter)
	{
		m_box2dworld    = world;
		m_pixelpermeter = pixelpermeter;
		
		m_groundbodydef = new BodyDef();
		m_groundbodydef.type = BodyDef.BodyType.StaticBody;
		m_groundbody = world.createBody(m_groundbodydef);

	}
	/**
	 * Renders the part of the map that should be visible to the user.
	 */
	public void render() {
		tileMapRenderer.getProjectionMatrix().set(camera.combined);

		Vector3 tmp = new Vector3();
		tmp.set(0, 0, 0);
		camera.unproject(tmp);

		tileMapRenderer.render((int) tmp.x, (int) tmp.y,
				Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), layersList);
	}

	public void createBoundMap()
	{
		// create bound for map
		EdgeShape mapBounds = new EdgeShape();
		// bottom line	
		mapBounds.set(new Vector2(0.0f, 0.0f), new Vector2(getWidth()/ m_pixelpermeter, 0.0f));
		m_groundbody.createFixture(mapBounds, 0);
		// top line
		mapBounds.set(new Vector2(0.0f, (getHeight()) / m_pixelpermeter),
				      new Vector2(getWidth() / m_pixelpermeter, (getHeight())/ m_pixelpermeter));
		m_groundbody.createFixture(mapBounds, 0);
		// left		
		mapBounds.set(new Vector2(0.0f, 0.0f), new Vector2(0.0f,getHeight() / m_pixelpermeter));
		m_groundbody.createFixture(mapBounds, 0);
		// right
		mapBounds.set(new Vector2(getWidth() / m_pixelpermeter, 0.0f),
				      new Vector2(getWidth() / m_pixelpermeter, getHeight()/ m_pixelpermeter));
		m_groundbody.createFixture(mapBounds, 0);
		mapBounds.dispose();
	}
	public void loadCollisonObject()
	{
		createBoundMap();
        for (TiledObjectGroup group : map.objectGroups) {
            for (TiledObject object : group.objects) {
				System.out.println("Object " + object.name + " x,y = " + object.x + "," + object.y + " width,height = "
						+ object.width + "," + object.height);				
				if(object.polyline!=null)
				{
					System.out.println("polygon: "+object.polyline);
					createBox2DPolylineObject( object.x, object.y,object.polyline);
				}
            }
        }
	}
	// 
	public void createBox2DPolylineObject(int px,int py,String points)
	{
		String lines[] = points.split(" ");
		py = 480 - py;             // <---------- HARCODED !!! 480: screen height
		EdgeShape mapBounds = new EdgeShape();
		int prevPx =0;
		int prevPy =0;
		for(int i=0;i<lines.length;i++) {
			//System.out.println("point "+i+" : "+lines[i]);
			String pointXY[] = lines[i].split(",");
			//System.out.println("x: "+pointXY[0]+" y: "+pointXY[1]);
			
			if(i==0) {
				prevPx =px+Integer.parseInt(pointXY[0]);
				prevPy =py-Integer.parseInt(pointXY[1]);
			}
			else {
				int nowPx =px+Integer.parseInt(pointXY[0]);
				int nowPy =py-Integer.parseInt(pointXY[1]);
				Vector2 point1 = new Vector2(prevPx/m_pixelpermeter,prevPy/m_pixelpermeter);
				Vector2 point2 = new Vector2(nowPx/m_pixelpermeter,nowPy/m_pixelpermeter);
				mapBounds.set(point1,point2);
				m_groundbody.createFixture(mapBounds, 0);
				prevPx = nowPx;
				prevPy = nowPy;
			}
		}
		mapBounds.dispose();
	}
	
	/**
	 * Get the height of the map in pixels
	 * 
	 * @return y
	 */
	public int getHeight() {
		return map.height * map.tileHeight;
	}

	/**
	 * Get the width of the map in pixels
	 * 
	 * @return x
	 */
	public int getWidth() {
		return map.width * map.tileWidth;
	}

	/**
	 * Get the map, useful for iterating over the set of tiles found within
	 * 
	 * @return TiledMap
	 */
	public TiledMap getMap() {
		return map;
	}

	/**
	 * Calls dispose on all disposable resources held by this object.
	 */
	public void dispose() {
		tileAtlas.dispose();
		tileMapRenderer.dispose();
	}

	/**
	 * Sets the directory that holds the game's pack files and tile sets.
	 * 
	 * @param packDirectory
	 */
	public void setPackerDirectory(String packDirectory) {
		packFileDirectory = Gdx.files.internal(packDirectory);
	}

	/**
	 * Loads the requested tmx map file in to the helper.
	 * 
	 * @param tmxFile
	 */
	public void loadMap(String tmxFile) {
		if (packFileDirectory == null) {
			throw new IllegalStateException("loadMap() called out of sequence");
		}

		map = TiledLoader.createMap(Gdx.files.internal(tmxFile));
		tileAtlas = new TileAtlas(map, packFileDirectory);

		tileMapRenderer = new TileMapRenderer(map, tileAtlas, 32, 32);

	}




	/**
	 * Prepares the helper's camera object for use.
	 * 
	 * @param screenWidth
	 * @param screenHeight
	 */
	public void prepareCamera(int screenWidth, int screenHeight) {
		camera = new OrthographicCamera(screenWidth, screenHeight);

		camera.position.set(0, 0, 0);
	}

	/**
	 * Returns the camera object created for viewing the loaded map.
	 * 
	 * @return OrthographicCamera
	 */
	public OrthographicCamera getCamera() {
		if (camera == null) {
			throw new IllegalStateException(
					"getCamera() called out of sequence");
		}
		return camera;
	}
	private FileHandle packFileDirectory;
	private OrthographicCamera camera;
	private TileAtlas tileAtlas;
	private TileMapRenderer tileMapRenderer;
	private TiledMap map;
}
